home *** CD-ROM | disk | FTP | other *** search
- ///////////////////////////////////////////////////////////////////////////////
- //
- // File: FlushPort.c
- //
- // Project: MacHack 2000 - Vertigo!
- // Authors: Darrin Cardani, Drew Thaler, Ed Wynne
- //
- // Date: 06/23/2000 (written entirely during the conference!)
- //
- ///////////////////////////////////////////////////////////////////////////////
-
- #include <alloca.h>
- #include <DriverServices.h>
- #include <Types.h>
- #include <Memory.h>
- #include <Quickdraw.h>
- #include <QDOffscreen.h>
- #include <Fonts.h>
- #include <Events.h>
- #include <Menus.h>
- #include <Windows.h>
- #include <TextEdit.h>
- #include <Dialogs.h>
- #include <OSUtils.h>
- #include <Sound.h>
- #include <string.h>
- #include <ToolUtils.h>
-
- #include "DebugUtils.h"
- #include "DrawingUtils.h"
- #include "DrawingFunctions.h"
- #include "FlushPort.h"
-
- // • Prototypes
- void main(void);
- void InitializeToolbox(void);
-
-
- // ----------------------------------------------------------------------------------
- // main
- // ----------------------------------------------------------------------------------
-
- /*
- void main(void)
- {
- // Set up the mac application.
- InitializeToolbox();
-
- // Create a couple of empty windows for show.
- Rect windowRects[] = { {300,450,600,800}, {100,100,450,600}, {240,444,464,989}, {256,196,645,732} };
- int numWindows = sizeof(windowRects) / sizeof(Rect);
- WindowPtr *windowList = (WindowPtr*)alloca(sizeof(WindowPtr)*numWindows);
- RegionList windowRegions;
-
- for (int i=0; i<numWindows; ++i)
- {
- windowList[i] = NewCWindow(NULL,&windowRects[i],"\pWindow",true,documentProc,(WindowPtr)-1L,false,0);
- windowRegions.Add(((WindowPeek)windowList[i])->strucRgn,true);
- }
-
- // Fetch the color window manager port.
- CGrafPtr wmgrPort;
- GetCWMgrPort(&wmgrPort);
-
- // Allocate a whole mess of GWorlds. Error checking is for pussies.
- StGWorld screenGWorld(wmgrPort);
- StGWorld dropShadowWorld(wmgrPort);
- StGWorld preShiftWorld(wmgrPort);
- StGWorld scratchWorld(wmgrPort);
- StGWorld postShiftWorld(wmgrPort);
-
- // Grab an image of the current screen.
- CopyPortToGWorld(wmgrPort,screenGWorld);
-
- // Create a window the same size as the screen, and display it. This doesn't
- // get us above floaters (like the stupid control strip), but it's fine for a test app.
- StHideMenuBar hideMenuBar;
- WindowPtr screenWindow = NewCWindow(NULL,&wmgrPort->portRect,"\pdrew's screen display",true,plainDBox,(WindowPtr)-1L,false,0);
-
- // Create a composite GWord for the output. Alternatively, composite onscreen for debugg.
- //StGWorld compositeWorld(wmgrPort);
- GWorldPtr compositeWorld = (CGrafPtr)screenWindow;
-
- {
- // For debugging, erase the composite world to black.
- {
- StSetGWorld setPort(compositeWorld);
- BackColor(blackColor);
- EraseRect(&((CGrafPtr)compositeWorld)->portRect);
- }
-
- // Time to doctor the screenshot with our code. For the test app,
- // we do the whole damn thing at once.
- StRegion maskRegion(*screenGWorld.PortRect());
-
- // Lay down some drop shadows.
- RenderDropShadows(screenGWorld,dropShadowWorld,maskRegion,windowRegions);
-
- // Loop across each window to do the red-shifting.
- const float maxDepth = 10;
- for (int i=-1; i<numWindows; ++i)
- {
- int windowIndex = numWindows - i;
- float depthToUse = maxDepth - (maxDepth / windowIndex);
- int inPlane = (windowIndex == 1);
- StRegion rgn;
-
- // Figure out which region we're starting with.
- if (i == -1)
- {
- rgn = wmgrPort->portRect;
- depthToUse = 10;
- }
- else
- {
- rgn = windowRegions[i];
- }
-
- // Subtract out all windows above it, and clip to our mask.
- for (int j=i+1; j<numWindows; ++j)
- rgn -= windowRegions[j];
- rgn &= maskRegion;
-
- // Skip if we've eliminated everything.
- if (rgn.IsEmpty()) continue;
-
- // Red shift if it's not in the plane... otherwise just copy it wholesale.
- if (!inPlane)
- {
- CopyRegionForRedShifting(dropShadowWorld,preShiftWorld,rgn);
- RedShiftAndBlur(preShiftWorld,scratchWorld,postShiftWorld,rgn,depthToUse);
- CopyIntoComposite(postShiftWorld,compositeWorld,rgn);
- }
- else
- {
- CopyIntoComposite(dropShadowWorld,compositeWorld,rgn);
- }
-
- // Blit our composited image back into visible space.
- CopyGWorldToPort(compositeWorld,screenWindow,maskRegion);
-
- // Wait for a mousedown. We WNE so drew can grab a screen shot.
- while (!Button()) { EventRecord ev; WaitNextEvent(everyEvent,&ev,0,NULL); SystemTask(); }
- while (Button()) {}
- }
- }
-
- // Hang out for a while.
-
- for (int i=0; i<numWindows; ++i)
- DisposeWindow(windowList[i]);
- DisposeWindow(screenWindow);
- }
-
-
- // ----------------------------------------------------------------------------------
- // InitializeToolbox
- // ----------------------------------------------------------------------------------
- void InitializeToolbox(void)
- {
- OSErr err;
- SysEnvRec theWorld;
-
- // Test the computer to be sure we can do color.
- // If not we would crash, which would be bad.
- // If we can’t run, just beep and exit.
- // (•• can you tell this code was descended from SillyBalls? ••)
- err = SysEnvirons(1, &theWorld);
- if (theWorld.hasColorQD == false) {
- SysBeep(50);
- ExitToShell();
- }
-
- // Initialize all the needed managers.
- InitGraf(&qd.thePort);
- InitFonts();
- InitWindows();
- InitMenus();
- TEInit();
- InitDialogs(nil);
- InitCursor();
-
- GetDateTime((unsigned long*) &qd.randSeed);
- if ((UInt32)UpTime != 0)
- qd.randSeed ^= UpTime().lo;
- }
-
- */
-
-
- // -- When passed a zero-based index, this function passes back the indicated
- // -- menu's rect (0=top-most, n-1=bottom-most). Returns false if no more menus.
-
- #define kMBSaveLoc 0x0B5C
- #define kLengthCookie 0x001C
-
- Boolean MenuSnitch(short menuIndex, Rect *menuRect);
- Boolean MenuSnitch(short menuIndex, Rect *menuRect)
- {
- Boolean result = false;
- short menuCount = 0;
- Handle mbSaveLoc = * (Handle *) kMBSaveLoc;
-
- if (mbSaveLoc)
- menuCount = (** (short **) mbSaveLoc) / kLengthCookie;
-
- if ((menuIndex >= 0) && (menuIndex < menuCount))
- {
- (*menuRect) = * (Rect *) (*mbSaveLoc +((menuIndex + 1) * kLengthCookie));
- result = true;
- }
-
- return(result);
- } // -- MenuSnitch
-
-
- extern GWorldPtr dropShadowWorld;
- extern GWorldPtr preShiftWorld;
- extern GWorldPtr scratchWorld;
- extern GWorldPtr postShiftWorld;
- extern GWorldPtr gStageBuffer;
-
-
- void RenderBufferOntoScreen(GWorldPtr srcWorld,GWorldPtr dstWorld,Rect *inRect,RgnHandle inMask)
- {
- THz oldZone = GetZone();
- SetZone(SystemZone());
-
- StRegion fullScreen(dstWorld->portRect);
-
- // Build a list of the window regions, in back-to-front order. We don't
- // include the desktop in this list.
- RegionList windowRegions;
- bool windowListChanged = false;
- BuildWindowList(windowRegions,windowListChanged);
-
- if (windowListChanged)
- {
- // Re-blit the entire screen.
- *inRect = dstWorld->portRect;
- CopyRgn(fullScreen,inMask);
- }
-
- // Lay down some fresh drop shadows.
- RenderDropShadows(srcWorld,dropShadowWorld,inMask,windowRegions);
-
- // Loop across each window to do the red-shifting.
- const float maxDepth = 10;
- int numWindows = windowRegions.GetCount();
- for (int i=-1; i<numWindows; ++i)
- {
- int windowIndex = numWindows - i;
- int depthToUse = maxDepth - (maxDepth / windowIndex);
- int inPlane = (windowIndex <= 2);
- StRegion rgn;
-
- // Figure out which region we're starting with.
- if (i == -1)
- {
- rgn = dstWorld->portRect;
- depthToUse = 10;
- }
- else
- {
- rgn = windowRegions[i];
- }
-
- // Subtract out all windows above it, and clip to our mask.
- for (int j=i+1; j<numWindows; ++j)
- rgn -= windowRegions[j];
- rgn &= inMask;
-
- // Skip if we've eliminated everything.
- if (rgn.IsEmpty()) continue;
-
- // Red shift if it's not in the plane... otherwise just copy it wholesale.
- if (!inPlane)
- {
- CopyRegionForRedShifting(dropShadowWorld,preShiftWorld,rgn);
- RedShiftAndBlur(preShiftWorld,scratchWorld,postShiftWorld,rgn,depthToUse);
- CopyIntoComposite(postShiftWorld,gStageBuffer,rgn);
- }
- else
- {
- CopyIntoComposite(dropShadowWorld,gStageBuffer,rgn);
- }
- }
-
- if (numWindows > 0)
- DisposeRgn(windowRegions[numWindows-1]);
-
- CopyGWorldToGWorld(gStageBuffer,dstWorld);
- SetZone(oldZone);
- }
-
-
- // --------------------------------------------------------
- // Single-app window list
- void
- BuildWindowList(RegionList &windowList, bool &windowListChanged)
- {
- static UInt32 oldList[1024] = {0};
- static UInt32 newList[1024] = {0};
- UInt32 *newListCursor = &newList[0];
- UInt32 remaining = 1024;
- ProcessSerialNumber currentProcess = { 0, kCurrentProcess };
- ProcessSerialNumber thisProcess = {0,0};
- Boolean same = false;
-
- // For now we only do the front app's windows. Yeah this is lame and sucks, but it'll
- // make us work for now.
- GetCurrentProcess(&thisProcess);
- if ((SameProcess(&thisProcess,¤tProcess,&same) != noErr) || !same)
- {
- windowListChanged = false;
- return;
- }
-
- // Since it's close to demo time...
- windowListChanged = true;
-
- // Grab the menu bar and the active menus.
- {
- StRegion rgn;
- GDHandle mainDevice = GetMainDevice();
-
- SetRectRgn(rgn,mainDevice[0]->gdRect.left,mainDevice[0]->gdRect.top,mainDevice[0]->gdRect.right,mainDevice[0]->gdRect.top+GetMBarHeight());
-
- // Add the current menu region here.
- Rect menuRect;
- short index = 0;
- while (MenuSnitch(index++,&menuRect))
- rgn += menuRect;
-
- windowList.Add(rgn,true);
- }
-
- // Grab the visible windows in front-to-back order.
- WindowPeek window = (*(WindowPeek*)0x9D6);
- while ((window != NULL) && (window != (WindowPeek)-1L))
- {
- if (window->visible)
- {
- windowList.Add(window->strucRgn,false);
-
- *(newListCursor++) = (UInt32)window;
- *(newListCursor++) = *(UInt32*)&window->strucRgn[0]->rgnBBox.top;
- *(newListCursor++) = *(UInt32*)&window->strucRgn[0]->rgnBBox.bottom;
- remaining -= 3;
-
- dprintf(kDConPrefix "Registering window %08X %08X %08X\n", *(newListCursor-3), *(newListCursor-2), *(newListCursor-1));
- }
-
- window = window->nextWindow;
- }
-
- // See if the window ordering or locations has changed since our last blit.
- BlockZero(newListCursor,remaining*4);
- if (!memcmp(oldList,newList,1024*4))
- {
- windowListChanged = true;
- BlockMoveData(newList,oldList,1024*4);
- }
-
- // Swap the windows in the list so that they're back-to-front.
- int count = windowList.GetCount();
- for (int i=0; i<count/2; ++i)
- {
- RgnHandle temp = windowList[i];
- windowList[count-i-1] = windowList[i];
- windowList[count-i-1] = temp;
- }
- }
-
-